package com.oocl.ita.sakura.server;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.oocl.ita.sakura.client.Client;
import com.oocl.ita.sakura.forwarder.Forwarder;

public class IMServer implements IServer {
	private ServerSocket serverSocket;
	// cSMap 在多线程情况下，CSMap要同步
	// private static Map<Client, Socket> cSMap = new HashMap(); //
	// 确定client和socket的对应关系
	private static Map<Client, ObjectOutputStream> clientOosMap = new HashMap();
	// private static List<Client> sList = new LinkedList(); // 遍历和增删，
	// 不用随机access
	// 只暴露有限的修改接口，且与CSMap保持同步

	// public static Map<UUID, Client> allClients; // 扩展： 只传uiid

	// 构造函数
	public IMServer(int port) {
		super();
		// TODO Auto-generated constructor stub
		try {
			this.serverSocket = new ServerSocket(port);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// daemon
	public void start() {
		while (true) {
			try {
				Socket clientSocket = serverSocket.accept();
				// UUID uid = UUID.randomUUID();
				System.out.println("IMServer : accept a new clientSocket");
				// !!!!!!不会在这里更新cSMap, 因为key 是Client，
				// 而Client的account属性还没确定。!!!!!!
				// 后悔上一句，如果socket在Client中，则socket一般不同，hashCode可以应付网络时序错乱的问题。可惜socket不在Client中
				// addClient(client, socket);
				new Thread(new Forwarder(clientSocket)).start();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	// 封装对 map <client , socket> 的更改
	public static ObjectOutputStream getOos(Client client) { // 获取某个Client的接口
		return clientOosMap.get(client);
	}

	public static void addClient(Client client, ObjectOutputStream oos) { // 要同步
		synchronized (clientOosMap) {
			clientOosMap.put(client, oos);
		}
	}

	public static void removeClient(Client client) { // 要同步
		synchronized (clientOosMap) {
			clientOosMap.remove(client);
		}
	}

	public static Map<Client, ObjectOutputStream> getClientOosMap() {
		return clientOosMap;
	}

}
